/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core.handlers.matchers;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.sourceforge.wurfl.core.Constants;
import net.sourceforge.wurfl.core.handlers.HandlersFactory;
import net.sourceforge.wurfl.core.handlers.classifiers.Filter;
import net.sourceforge.wurfl.core.handlers.classifiers.FilterChain;
import net.sourceforge.wurfl.core.handlers.classifiers.FilterChainFactory;
import net.sourceforge.wurfl.core.handlers.classifiers.FilteredDevices;
import net.sourceforge.wurfl.core.request.WURFLRequest;
import net.sourceforge.wurfl.core.resource.ModelDevice;
import net.sourceforge.wurfl.core.resource.WURFLModel;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This class is responsible to manage the matching process. It is a facade
 * class of {@link Matcher}s an {@link Filter}s.
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: MatcherManager.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public class MatcherManager {

	/** The matcher chain-of-responsibility used to match user-agents */
	private final MatcherChain matcherChain;

	/** The Filter chain used to classify devices */
	private final FilterChain filterChain;

	/** Logger */
	private static final Log log = LogFactory.getLog(MatcherManager.class);

	// Constructors *******************************************************

	/**
	 * Build a MatcherManager by model, matcher chain and filter chain.
	 * 
	 * @param model
	 *            The WURFLModel used to get devices from.
	 * @param filterChain
	 *            The used FilterChain.
	 * @param matcherChain
	 *            The used MatcherChain.
	 */
	public MatcherManager(WURFLModel model, FilterChain filterChain,
			MatcherChain matcherChain) {

		this.filterChain = filterChain;
		this.matcherChain = matcherChain;

		addFilteredDevices(model.getAllDevices());
	}

	/**
	 * Build a MatcherManager by model.
	 * 
	 * @param model
	 *            The WURFLModel used to get devices from.
	 */
	public MatcherManager(WURFLModel model) {

		Map handlers = new HandlersFactory().create();

		filterChain = new FilterChainFactory(handlers).create();
		matcherChain = new MatcherChainFactory(handlers).create();

		addFilteredDevices(model.getAllDevices());
	}

	// Business methods ***************************************************

	/**
	 * Match the request to obtain a device identifier. For more info look at
	 * {@link Matcher#match(WURFLRequest)}.
	 * 
	 * @param request
	 *            The {@link WURFLRequest} to match.
	 * @return A valid device identifier, <code>generic</code> device at least.
	 */
	public String matchRequest(WURFLRequest request) {

		FilteredDevices filteredDevices = filterChain
				.getFilteredDevices(request.getUserAgent());

		return matcherChain.match(request, filteredDevices);

	}

	/**
	 * Add devices to be collected.
	 * 
	 * @param devices
	 *            Set of ModelDevice to be collected by matchers.
	 */
	protected void addFilteredDevices(Set/* ModelDevice */devices) {

		for (Iterator iterator = devices.iterator(); iterator.hasNext();) {

			ModelDevice device = (ModelDevice) iterator.next();
			String userAgent = device.getUserAgent();
			String deviceId = device.getID();

			// Integrity check in model
			if (StringUtils.isNotBlank(userAgent)) {

				if (log.isDebugEnabled()) {
					log.debug("Filter UA: " + userAgent + " deviceId: "
							+ deviceId);
				}

				filterChain.filter(userAgent, deviceId);
			} else if(!Constants.GENERIC.equals(deviceId)) {
				log.warn("Found null user-agent in filtering, deviceId:"
						+ deviceId);
			}

		}

	}

}
